Skip to content

Conversation

Girgias
Copy link
Member

@Girgias Girgias commented Aug 24, 2025

Copy link

AWS x86_64 (c7i.24xl)

Attribute Value
Environment aws
Runner host
Instance type c7i.metal-24xl (dedicated)
Architecture x86_64
CPU 48 cores
CPU settings disabled deeper C-states, disabled turbo boost, disabled hyper-threading
RAM 188 GB
Kernel 6.1.147-172.266.amzn2023.x86_64
OS Amazon Linux 2023.8.20250818
GCC 14.2.1
Time 2025-08-29 17:20:09 UTC

Laravel 12.2.0 demo app - 100 consecutive runs, 50 warmups, 100 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.46565 0.46818 0.00045 0.10% 0.46637 0.00% 0.46629 0.00% 1.515 0.999 176423932 44.01 MB
PHP - 8.5-warn-nan-coercion 0.45876 0.46679 0.00075 0.16% 0.46494 -0.31% 0.46499 -0.28% -5.442 0.000 176485965 44.07 MB

Symfony 2.7.0 demo app - 100 consecutive runs, 50 warmups, 100 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.72046 0.73259 0.00155 0.21% 0.72261 0.00% 0.72217 0.00% 3.109 0.999 287234974 40.16 MB
PHP - 8.5-warn-nan-coercion 0.72253 0.72854 0.00100 0.14% 0.72405 0.20% 0.72384 0.23% 1.831 0.000 287280133 40.53 MB

Wordpress 6.2 main page - 100 consecutive runs, 20 warmups, 20 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.57464 0.58357 0.00228 0.39% 0.58060 0.00% 0.58151 0.00% -1.225 0.999 1119139470 43.91 MB
PHP - 8.5-warn-nan-coercion 0.57682 0.58512 0.00218 0.37% 0.58209 0.26% 0.58298 0.25% -1.361 0.000 1119813967 43.91 MB

bench.php - 100 consecutive runs, 10 warmups, 2 requests (sec)

PHP Min Max Std dev Rel std dev % Mean Mean diff % Median Median diff % Skew P-value Instr count Memory
PHP - baseline@fc46 0.42476 0.55444 0.02724 6.28% 0.43407 0.00% 0.42786 0.00% 4.179 0.999 2020744423 26.98 MB
PHP - 8.5-warn-nan-coercion 0.42534 0.58863 0.03210 7.34% 0.43703 0.68% 0.42765 -0.05% 3.477 0.582 2020694323 27.05 MB

@@ -7728,7 +7728,14 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32
if_double = ir_IF(ir_EQ(type, ir_CONST_U8(IS_DOUBLE)));
ir_IF_TRUE(if_double);
}
ref = ir_NE(jit_Z_DVAL(jit, op1_addr), ir_CONST_DOUBLE(0.0));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to avoid calling zend_is_true() during compilation above when the value is a const nan, otherwise we emit two warnings here: (during tracing, then while compiling the trace)

echo (bool)NAN;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done a check, but now the function JIT doesn't emit a warning :/

Comment on lines +485 to +486
* Those optimizations are not safe if the other operand end up being NAN
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triggered a benchmark to check the effect of this: valgrind shows no regression (changes are under 0.0x%).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder if this is not actually a problem for switch cases too now that I think of.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be worth it to check

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it seems I completely broke switch statements...

<?php

$nan = fdiv(0, 0);
switch ($nan) {
    case true:
        echo "true";
        break;
    case false:
        echo "false";
        break;
}
?>

Returns nothing now, even without opcache :|

@Girgias Girgias force-pushed the 8.5-warn-nan-coercion branch from 729488f to 37c74ce Compare August 31, 2025 17:15
@Girgias Girgias force-pushed the 8.5-warn-nan-coercion branch from 37c74ce to 7c29b7f Compare August 31, 2025 17:17
@Girgias Girgias requested a review from arnaud-lb September 1, 2025 21:55
Comment on lines 7565 to 7570
if (Z_MODE(op1_addr) == IS_CONST_ZVAL) {
if (zend_is_true(Z_ZV(op1_addr))) {
zval *op1 = Z_ZV(op1_addr);
/* NAN Value must cause a warning to be emitted */
// TODO function JIT does not emit warning
if ((Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1))) || zend_is_true(op1)) {
always_true = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because the cast gets optimized to a constant true when setting always_true = 1. You need to skip the if (Z_MODE(op1_addr) == IS_CONST_ZVAL) { branch entirely when it's nan.

@@ -16,6 +16,7 @@
* +----------------------------------------------------------------------+
*/

#include "../../../Zend/zend_types.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include "../../../Zend/zend_types.h"
#include "Zend/zend_types.h"

Comment on lines +485 to +486
* Those optimizations are not safe if the other operand end up being NAN
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be worth it to check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants